<template>
  <div ref="container" class="container"></div>
</template>
<script setup lang="ts">
// Gsap库做动画
import gsap from "gsap";
import * as THREE from "three";
import { ref, onMounted } from "vue";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

// gat.dui 库  图形化控制页面
import * as dat from "dat.gui";
//初始换场景
const scene = new THREE.Scene();

//创建相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

//设置相机的位置
camera.position.set(0, 0, 20); //轨道0.01才能动

//矩形里面看房

//房屋照片集合  材质
// const materials: THREE.MeshBasicMaterial[] = [];

//一间屋子有  上下左右前后  六个面  所以创建6面墙的图片   现在是放在一个正方体里面了   （球体的话要全景相机拍摄）
//
// const texture_right = new THREE.TextureLoader().load("./images/chuFang.jpg");
// materials.push(new THREE.MeshBasicMaterial({ map: texture_right }));
//
// const texture_left = new THREE.TextureLoader().load("./images/ciWo.jpg");
// materials.push(new THREE.MeshBasicMaterial({ map: texture_left }));
//
// const texture_front = new THREE.TextureLoader().load("./images/zhuWo.jpg");
// materials.push(new THREE.MeshBasicMaterial({ map: texture_front }));
//
// const texture_back = new THREE.TextureLoader().load("./images/menTing.jpg");
// materials.push(new THREE.MeshBasicMaterial({ map: texture_back }));
//
// const texture_top = new THREE.TextureLoader().load("./images/shuFang.jpg");
// materials.push(new THREE.MeshBasicMaterial({ map: texture_top }));
//
// const texture_bottom = new THREE.TextureLoader().load("./images/keTing.jpg");
// materials.push(new THREE.MeshBasicMaterial({ map: texture_bottom }));

//创建几何体   宽高深  据图文档可以启动three源码查看docs文档
const geomertry = new THREE.BoxGeometry(10, 10, 10);
// const v3 = new THREE.Vector3(0, 0, 0); //在坐标轴的位置  xyz
// const e3 = new THREE.Euler(0, 10, 0); //沿哪个轴旋转。
//创建材质  vr看房，后面还是图片包裹  材质随意设置 看中文
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); //材质放背景图以后不要了

//创建网格
const box = new THREE.Mesh(geomertry, material);
// box.position.copy(v3);
// box.rotation.copy(e3);
// 放入场景
scene.add(box);

//移动，一个房间移动到另一个房间 会用到
gsap.to(box.position, {
  x: 10,
  y: 10, //x, y, rotation‌：定义动画的属性，如位置和旋转角度
  duration: 2,
  repeat: 2, //动画重复次数  -1无限循环
  yoyo: true, //是否启用来回移动
  delay: 0.5,
  ease: "power1.out", //缓动函数  定义动画速度曲线
}); //现在就用这一个动画方法

gsap.to(box.rotation, { z: 15, duration: 2, repeat: 2 });

//图形化控制页面
const gui = new dat.GUI();
gui.add(box.position, "x").name("移动x轴").min(-5).max(5).step(0.1); // 移动目标  目标的什么属性  叫什么  最大小最大  步长
gui.add(box.position, "y").name("移动y轴").min(-5).max(5).step(0.1);
gui.add(box.position, "z").name("移动z轴").min(-5).max(5).step(0.1);
gui
  .addColor({ color: "#00ff00" }, "color")
  .name("修改颜色")
  .onChange((e) => {
    box.material.color = new THREE.Color(e);
  }); //调色板

const boxFolder = gui.addFolder("立方体属性"); //分组
boxFolder.add(box.position, "x").name("移动x轴").min(-5).max(5).step(0.1);
boxFolder.add(box.position, "z").name("移动z轴").min(-5).max(5).step(0.1);
boxFolder.open(); //初始化展开

//结合
const params = {
  visible: true,
  moveAnimation: () => {
    gsap.to(box.position, { x: 5, duration: 2 });
  },
};

boxFolder
  .add(params, "visible")
  .name("是否可见")
  .onChange((e) => {
    box.visible = e;
  });
boxFolder.add(params, "moveAnimation").name("移动动画");

const cameraFolder = gui.addFolder("相机属性");
cameraFolder
  .add(camera.position, "x")
  .name("相机的x轴")
  .min(-30)
  .max(30)
  .step(0.1);
cameraFolder
  .add(camera.position, "y")
  .name("相机的y轴")
  .min(-30)
  .max(30)
  .step(0.1);
cameraFolder
  .add(camera.position, "z")
  .name("相机的z轴")
  .min(-30)
  .max(30)
  .step(0.1);
cameraFolder
  .add(camera.rotation, "z")
  .name("相机z轴旋转")
  .min(-5)
  .max(5)
  .step(0.1);

cameraFolder.open();

// 视口监听
window.addEventListener("resize", () => {
  //随着视口变化更新宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 更新相机的投影矩阵
  camera.updateProjectionMatrix();
  // 更新渲染前的大小
  renderer.setSize(window.innerWidth, window.innerHeight);
});

//添加坐标辅助器
const axesHelper = new THREE.AxesHelper(20); //参数是轴线长度
scene.add(axesHelper);
//控制器
let controls: OrbitControls;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();

//设置渲染器的大小
renderer.setSize(window.innerWidth, window.innerHeight);

const container = ref<HTMLElement | null>(null);

const render = () => {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
  //requestAnimationFrame: 在浏览器下一次重绘之前调用指定的回调函数，确保动画与页面刷新同步，从而实现更流畅的动画效果。
  // 相比 setTimeout 或 setInterval，requestAnimationFrame 更加效率高，能自动调整动画帧率（通常是 60fps），并在标签切换或页面隐藏时自动暂停。
  // 在函数内可以更新元素位置、样式等，实现动画效果
  // 不断调用自我（递归）实现连续动画
};
onMounted(() => {
  if (container.value) {
    controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true; //阻尼感
    controls.update();
    container.value.appendChild(renderer.domElement);
    render();
  }
});
</script>

<style scoped lang="scss">
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.container {
  width: 100vw;
  height: 100vh;
  background-color: #000;
}
</style>
